<template>
  <div class="monaco-editor-box">
    <div
        class="monaco-editor-el"
        :id="monacoEditorId"
        :class="{'is-focus':monacoFocus}"
        :style="style"></div>
  </div>


</template>
<script>
import props from "components/avue/core/common/props";
import event from "components/avue/core/common/event";
import * as monaco from "monaco-editor";
import {deepClone} from "utils/util";

export default {
  name: "avue-monaco-edit",
  mixins: [props(), event()],
  props: {
    diffEditor: {type: Boolean, default: false},
    width: {type: [String, Number], default: '100%'},
    height: {type: [String, Number], default: '100%'},
    minHeight: {type: [String, Number], default: '200'},
    original: String,
    language: {type: String, default: 'text'},
    theme: {type: String, default: 'vs'},
    options: {
      type: Object,
      default() {
        return {}
      },
    },
  },
  watch: {
    options: {
      deep: true,
      handler(options) {
        this.editor.updateOptions(options)
      },
    },
    original() {
      this._setOriginal()
    },
    language() {
      if (!this.editor) return
      if (this.diffEditor) {
        const {original, modified} = this.editor.getModel()
        monaco.editor.setModelLanguage(original, this.language)
        monaco.editor.setModelLanguage(modified, this.language)
      } else
        monaco.editor.setModelLanguage(this.editor.getModel(), this.language)
    },
    theme() {
      monaco.editor.setTheme(this.theme)
    },
    readonly() {
      this._updateReadOnlyOptions()
    },
    disabled() {
      this._updateReadOnlyOptions()
    }
  },
  computed: {
    style() {
      const height = this.height
      const minHeight = this.minHeight
      const width = this.width
      const fixedWidth = width.toString().includes('%') ? width : `${width}px`
      const fixedHeight = height.toString().includes('%') ? height : `${height}px`
      const fixedMinHeight = minHeight.toString().includes('%') ? minHeight : `${minHeight}px`
      return {
        width: fixedWidth,
        height: fixedHeight,
        minHeight: fixedMinHeight,
      }
    },
  },
  data() {
    return {
      monacoFocus: false,
      monacoEditorId: "monaco-editor_" + Math.random(),
      monacoEditorEl: null,
    }
  }
  ,
  mounted() {

    this.initMonaco()
  },
  methods: {
    initMonaco() {
      this.initVal();
      this.monacoEditorEl = document.getElementById(this.monacoEditorId)
      this.$emit('editorWillMount', monaco)
      const {text, language, theme, options} = this
      let readOnly = this.readonly || this.disabled
      if (readOnly === null || readOnly === undefined) {
        readOnly = false
      }
      let editorValue=text
      if(editorValue===null||editorValue===undefined){
        editorValue="";
      }

      this.editor = monaco.editor['create'](this.monacoEditorEl, {
        value: editorValue,
        language: language,
        theme: theme,
        automaticLayout: true,
        readOnly: readOnly,
        ...options,
      })
      this.diffEditor && this._setModel(this.modelValue, this.original)
      const editor = this._getEditor();
      editor.onDidChangeModelContent((event) => {
        this.text = editor.getValue()
      })
      this.$emit('editorDidMount', this.editor)

      this.editor.onDidFocusEditorText((e) => {

        this.monacoFocus = true
        this.handleFocus("focus")
      });

      this.editor.onDidBlurEditorText(() => {
        this.monacoFocus = false
        this.handleBlur("blur")
      });


    },
    handleModelValue(val) {
      if (val === this._getValue()) {
        return
      }
      this._setValue(val)
    },
    _setModel(value, original) {
      const {language} = this
      const originalModel = monaco.editor.createModel(original, language)
      const modifiedModel = monaco.editor.createModel(value, language)
      this.editor.setModel({
        original: originalModel,
        modified: modifiedModel,
      })
    },
    _setValue(value) {
      let editor = this._getEditor()
      if (editor) return editor.setValue(value)
    },
    _getValue() {
      let editor = this._getEditor()
      if (!editor) return ''
      return editor.getValue()
    },
    _getEditor() {
      if (!this.editor) return null
      return this.diffEditor ? this.editor.modifiedEditor : this.editor
    },
    _setOriginal() {
      const {original} = this.editor.getModel()
      original.setValue(this.original)
    },
    _updateReadOnlyOptions() {
      let readOnly = this.readonly || this.disabled
      if (readOnly === null || readOnly === undefined) {
        readOnly = false
      }
      this._updateOptions({readOnly: readOnly})
    },
    _updateOptions(option) {
      let clone = deepClone(option || {});
      let codeEditor = this._getEditor();
      if (!codeEditor) {
        return
      }
      codeEditor.updateOptions(clone)
    }
  },
  beforeUnmount() {
    this.editor && this.editor.dispose()
  },
}

</script>
<style lang="scss">

.monaco-editor-box {
  padding-right: 24px;
  padding-top: 1px;

  .monaco-editor-el {
    box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;
    border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
    padding: 11px;

    .monaco-editor {
      .minimap {
        z-index: 1;
      }
    }

    &.is-focus {
      box-shadow: 0 0 0 1px var(--el-color-primary);

    }

    .margin {
      margin: 0px;
    }

  }


}
</style>